package com.ms.test11;

import java.util.concurrent.TimeUnit;

/**
 *
 * 请编写一个多线程程序，实现两个线程，一个线程完成对某个对象 int成员变量的增加操作，即每次+1；
 * 另外一个线程完成该对象的成员变量的减操作，即每次 -1 ；
 * 同时要保证该变量的值不会小于0，不会大于1，该变量的初始值为0；
 * 01010101
 *
 * 多线程的协作，使用  wait ， notify  ;
 *
 * 关于 wait,notify,notifyAll,sleep的关系：
 * wait:
 * 1，如果一个线程调用了某个对象的wait方法，那么该线程必须拥有该对象的锁；
 * （换句话说如果一个线程调用了某个对象的wait方法，那么该wait方法必须在synchronized中）
 *2，如果一个线程调用了某个对象的wait方法，那么该线程就会释放该对象的锁；
 * 3，在java对象中，有两种池（锁池，等待池）
 * 4,如果一个线程 调用了某个对象的wait方法，那么该线程进入该对象的等待池中；释放锁；
 * 如果未来的某一时刻，或者另外的一个线程调用了相同对象的notify或者notifyAll方法，
 * 那么在该等待池中等待的线程就会起来，进入该对象的锁池中去等待获得该对象的锁；
 *如果获得锁成功，那么该线程将继续沿着wait方法之后的路径去执行；
 *
 * sleep（）：
 * 如果一个线程调用了sleep方法，不会释放对象的锁的拥有权；
 *
 * @author carter
 * create time    2018-08-20
 */
public class TestThread {

    public static void main(String[] args) {


        Sample sample = new Sample(0);
        new IncreaseThread(sample).start();
        new DecreaseThread(sample).start();
        new IncreaseThread(sample).start();
        new DecreaseThread(sample).start();


    }


}

class Sample {
    private Integer  num = 0;



    public Sample(Integer num)
    {
        this.num = num;
    }


    public synchronized void setNumIncre() {
        while (num!= 0)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            this.num++;
            notify();

        System.out.println(Thread.currentThread().getName() + ": "+ num);

    }
    public synchronized void setNumDecre() {

        while (num != 1)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

            this.num--;
            notify();

        System.out.println(Thread.currentThread().getName() + ": "+ num);
    }
}

class IncreaseThread extends Thread{

    private Sample sample;

    public IncreaseThread(Sample sample)
    {
        this.sample = sample;
    }

    @Override
    public void run() {
        for (int i=0;i<20;i++)
        {
            try {
                TimeUnit.SECONDS.sleep(1);
                this.sample.setNumIncre();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

class DecreaseThread extends Thread{

    private Sample sample;

    public DecreaseThread(Sample sample)
    {
        this.sample = sample;
    }

    @Override
    public void run() {
        for (int i=0;i<20;i++)
        {
            try {
                TimeUnit.SECONDS.sleep(1);
                this.sample.setNumDecre();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}


